package com.xusheng.cli.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xusheng.cli.common.base.MyPage;
import com.xusheng.cli.common.base.MyServiceImpl;
import com.xusheng.cli.common.exception.ServiceException;
import com.xusheng.cli.common.tools.UnitConvertUtils;
import com.xusheng.cli.entity.clarityModule.Clarity;
import com.xusheng.cli.entity.dictionaryModule.Category;
import com.xusheng.cli.entity.favoritesModule.Favorites;
import com.xusheng.cli.entity.frontUserModule.FrontUser;
import com.xusheng.cli.entity.frontUserModule.WatchingRecord;
import com.xusheng.cli.entity.likesModule.Likes;
import com.xusheng.cli.entity.videoModule.ShortVideoVO;
import com.xusheng.cli.entity.videoModule.Video;
import com.xusheng.cli.mapper.VideoMapper;
import com.xusheng.cli.req.VideoQueryReq;
import com.xusheng.cli.service.*;
import com.xusheng.cli.tools.CurrentPlayerUserUtil;
import com.xusheng.cli.tools.StpPlayerUtil;
import icu.mhb.mybatisplus.plugln.core.JoinLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.xusheng.cli.common.enums.ResultEnum.*;

@Slf4j
@Service
public class VideoServiceImpl extends MyServiceImpl<VideoMapper, Video> implements VideoService {

    @Resource
    private WatchingRecordService watchingRecordService;
    @Resource
    private FrontUserService frontUserService;
    @Resource
    private FavoritesService favoritesService;
    @Resource
    private LikesService likesService;
    @Resource
    private ClarityService clarityService;

    @Override
    public MyPage<Video> videoList(VideoQueryReq req) {
        JoinLambdaWrapper<Video> wrapper = new JoinLambdaWrapper<>(Video.class)
                .gt(req.getStartTime() != null, Video::getCreateTime, req.getStartTime())
                .lt(req.getEndTime() != null, Video::getCreateTime, req.getEndTime())
                .eq(req.getCategoryId() != null, Video::getCategoryId, req.getCategoryId())
                .like(req.getTitle() != null, Video::getTitle, req.getTitle())
                .eq(req.getVip() != null, Video::getVip, req.getVip())
                .eq(req.getShortVideo() != null, Video::getShortVideo, req.getShortVideo())
                .orderByDesc(Video::getCreateTime)
                .leftJoin(Category.class, Category::getId, Video::getCategoryId)
//                .rightJoin(Category.class, Category::getId, Video::getCategoryId)
                .selectAs(Category::getName, "category")
                .end();
        return baseMapper.joinSelectPage(req.getPage(), wrapper, Video.class);
    }

    @Override
    public boolean deleteVideo(long id) {
        return deleteWithFill(new Video(), Wrappers.<Video>lambdaQuery().eq(Video::getId, id));
    }

    @Override
    public Map<String, Object> videoDetail(long id, long userId) {
        Map<String, Object> data = new HashMap<>();
        Video video = getById(id);
        video.setUrl(null);
        video.setFavorites(false);
        video.setLikes(false);
        if (userId != 0) {
            long favoritesCount = favoritesService.count(Wrappers.<Favorites>lambdaQuery()
                    .eq(Favorites::getUserId, userId)
                    .eq(Favorites::getVideoId, id));
            if (favoritesCount > 0) video.setFavorites(true);
            long likesCount = likesService.count(Wrappers.<Likes>lambdaQuery()
                    .eq(Likes::getUserId, userId)
                    .eq(Likes::getVideoId, id));
            if (likesCount > 0) video.setLikes(true);
        }
        List<Video> list = recommendList(video.getCategoryId());
        for (Video v : list) {
            // 获取收藏数量
            Favorites favorites = new Favorites();
            favorites.setVideoId(v.getId());
            long favoritesCount = favoritesService.count(new QueryWrapper<>(favorites));
            v.setFavoritesCount(favoritesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(favoritesCount) : StrUtil.toString(favoritesCount));
            // 获取点赞数量
            Likes likes = new Likes();
            likes.setVideoId(v.getId());
            long likesCount = likesService.count(new QueryWrapper<>(likes));
            v.setLikesCount(likesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(likesCount) : StrUtil.toString(likesCount));
        }
        data.put("video", video);
        data.put("recommend", list);
        return data;
    }

    @Override
    public Map<String, Object> playVideo(long videoId) {
        Video video = getById(videoId);
        FrontUser user = frontUserService.getById(CurrentPlayerUserUtil.getUserId());
        if (video == null) throw new ServiceException("视频不存在");
        // 添加单次观看之后扣除次数
        if (video.getVip()) {
            // 未登录
            if (!StpPlayerUtil.isLogin()) {
                throw new ServiceException("该视频需登录后观看", AUTH_FAIL);
            }
            if ((user.getVipId() == null || user.getVipId() == 0L) && user.getVipExpires() == null) {
//                if (user.getWatchCount() > 0) {
//                    user.setWatchCount(user.getWatchCount() - 1);
//                    frontUserService.updateById(user);
//                } else {
                throw new ServiceException("该视频需开通会员观看", NEED_VIP);
//                }
            } else if (user.getVipExpires().isBefore(LocalDateTime.now())) {
//                if (user.getWatchCount() > 0) {
//                    user.setWatchCount(user.getWatchCount() - 1);
//                    frontUserService.updateById(user);
//                } else {
                throw new ServiceException("会员已过期无法观看此视频", RENEW_VIP);
//                }
            }
        } else {
            // 非会员视频
            if ((user.getVipId() == null || user.getVipId() == 0L) && user.getVipExpires() == null) {
                if (user.getWatchCount() > 0) {
                    user.setWatchCount(user.getWatchCount() - 1);
                    frontUserService.updateById(user);
                } else {
                    throw new ServiceException("今日剩余观影次数为0，请充值会员或明天再来", NO_COUNT);
                }
            } else if (user.getVipExpires().isBefore(LocalDateTime.now())) {
                if (user.getWatchCount() > 0) {
                    user.setWatchCount(user.getWatchCount() - 1);
                    frontUserService.updateById(user);
                } else {
                    throw new ServiceException("今日剩余观影次数为0，请充值会员或明天再来", NO_COUNT);
                }
            }
        }

        // 添加播放记录
        if (StpPlayerUtil.isLogin()) {
            Long userId = CurrentPlayerUserUtil.getUserId();
            WatchingRecord record = new WatchingRecord();
            record.setVideoId(videoId);
            record.setUserId(userId);
            LambdaQueryWrapper<WatchingRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WatchingRecord::getVideoId, video.getId()).eq(WatchingRecord::getUserId, userId);
            long count = watchingRecordService.count(wrapper);
            boolean success;
            if (count > 0) success = watchingRecordService.update(new LambdaUpdateWrapper<WatchingRecord>()
                    .eq(WatchingRecord::getUserId, userId)
                    .eq(WatchingRecord::getVideoId, videoId)
                    .set(WatchingRecord::getUpdateTime, LocalDateTime.now()));
            else
                success = watchingRecordService.save(record);
            if (!success) {
                log.error("保存视频播放记录失败：" + record);
                throw new ServiceException("视频播放失败");
            }
        }
        Map<String, Object> data = new HashMap<>();
        List<Video> list = recommendList(video.getCategoryId());
        for (Video v : list) {
            // 获取收藏数量
            Favorites favorites = new Favorites();
            favorites.setVideoId(v.getId());
            long favoritesCount = favoritesService.count(new QueryWrapper<>(favorites));
            v.setFavoritesCount(favoritesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(favoritesCount) : StrUtil.toString(favoritesCount));
            // 获取点赞数量
            Likes likes = new Likes();
            likes.setVideoId(v.getId());
            long likesCount = likesService.count(new QueryWrapper<>(likes));
            v.setLikesCount(likesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(likesCount) : StrUtil.toString(likesCount));
        }
        data.put("video", video);
        data.put("recommend", list);
        return data;
    }

    @Override
    public Map<String, Object> playVideoNew(long videoId) {
        Video video = getById(videoId);
        FrontUser user = frontUserService.getById(CurrentPlayerUserUtil.getUserId());
        if (video == null) throw new ServiceException("视频不存在");
        List<Clarity> clarityList = clarityService.list(new LambdaQueryWrapper<>(new Clarity()).eq(Clarity::getVideoId, videoId).orderByAsc(Clarity::getCreateTime));
//        for (Clarity item : clarityList) {
//            if (item.getSource() == 0) {
//                item.setUrl(item.getIp() + item.getUrl());
//            }
//            log.info("视频路径：" + item.getUrl());
//        }
        video.setClarityList(clarityList);
        // 添加单次观看之后扣除次数
        if (video.getVip()) {
            // 未登录
            if (!StpPlayerUtil.isLogin()) {
                throw new ServiceException("该视频需登录后观看", AUTH_FAIL);
            }
            if ((user.getVipId() == null || user.getVipId() == 0L) && user.getVipExpires() == null) {
                throw new ServiceException("该视频需开通会员观看", NEED_VIP);
            } else if (user.getVipExpires().isBefore(LocalDateTime.now())) {
                throw new ServiceException("会员已过期无法观看此视频", RENEW_VIP);
            }
        } else {
            if (user == null) {

            } else {
                // 非会员视频
                if ((user.getVipId() == null || user.getVipId() == 0L) && user.getVipExpires() == null) {
                    if (user.getWatchCount() > 0) {
                        user.setWatchCount(user.getWatchCount() - 1);
                        frontUserService.updateById(user);
                    } else {
                        throw new ServiceException("今日剩余观影次数为0，请充值会员或明天再来", NO_COUNT);
                    }
                } else if (user.getVipExpires().isBefore(LocalDateTime.now())) {
                    if (user.getWatchCount() > 0) {
                        user.setWatchCount(user.getWatchCount() - 1);
                        frontUserService.updateById(user);
                    } else {
                        throw new ServiceException("今日剩余观影次数为0，请充值会员或明天再来", NO_COUNT);
                    }
                }
            }
        }
        // 添加播放记录
        if (StpPlayerUtil.isLogin()) {
            Long userId = CurrentPlayerUserUtil.getUserId();
            WatchingRecord record = new WatchingRecord();
            record.setVideoId(videoId);
            record.setUserId(userId);
            LambdaQueryWrapper<WatchingRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WatchingRecord::getVideoId, video.getId()).eq(WatchingRecord::getUserId, userId);
            long count = watchingRecordService.count(wrapper);
            boolean success;
            if (count > 0) success = watchingRecordService.update(new LambdaUpdateWrapper<WatchingRecord>()
                    .eq(WatchingRecord::getUserId, userId)
                    .eq(WatchingRecord::getVideoId, videoId)
                    .set(WatchingRecord::getUpdateTime, LocalDateTime.now()));
            else
                success = watchingRecordService.save(record);
            if (!success) {
                log.error("保存视频播放记录失败：" + record);
                throw new ServiceException("视频播放失败");
            }
        }
        Map<String, Object> data = new HashMap<>();
        List<Video> list = recommendList(video.getCategoryId());
        for (Video v : list) {
            // 获取收藏数量
            Favorites favorites = new Favorites();
            favorites.setVideoId(v.getId());
            long favoritesCount = favoritesService.count(new QueryWrapper<>(favorites));
            v.setFavoritesCount(favoritesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(favoritesCount) : StrUtil.toString(favoritesCount));
            // 获取点赞数量
            Likes likes = new Likes();
            likes.setVideoId(v.getId());
            long likesCount = likesService.count(new QueryWrapper<>(likes));
            v.setLikesCount(likesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(likesCount) : StrUtil.toString(likesCount));
        }
        data.put("video", video);
        data.put("recommend", list);
        return data;
    }

    @Override
    public List<Video> rankList(long categoryId, int limit) {
        LocalDateTime endTime = LocalDateTime.now();
        List<Video> list = baseMapper.videoList(categoryId, endTime.plusDays(-7), endTime, limit);
        list.forEach(v -> {
            if (v.getSource() == 0) v.setUrl(null);
        });
        return list;
    }

    private List<Video> recommendList(long categoryId) {
        LocalDateTime endTime = LocalDateTime.now();
        List<Video> list = baseMapper.videoList(categoryId, endTime.plusDays(-7), endTime, 8);
        if (list.isEmpty()) list = lambdaQuery().eq(Video::getCategoryId, categoryId)
                .orderByDesc(Video::getCreateTime)
                .last("limit 8")
                .list();
        list.forEach(v -> {
            if (v.getSource() == 0) v.setUrl(null);
        });
        return list;
    }

    /**
     * 获取播放量排行视频
     *
     * @return
     */
    @Override
    public List<Video> listByPlayCount() {
        return baseMapper.listByPlayCount();
    }

    /**
     * 获取点赞量排行视频
     *
     * @return
     */
    @Override
    public List<Video> listByLikeCount() {
        return baseMapper.listByLikeCount();
    }

    /**
     * @param userId
     * @param vip
     * @param current
     * @return
     */
    @Override
    public List<ShortVideoVO> getShortVideoList(Long userId, Boolean vip, int current) {
        return baseMapper.getShortVideoList(userId, vip, current);
    }

    /**
     * @return
     */
    @Override
    public List<Video> recommendList() {
        List<Video> videoList;
        long count = count(new LambdaQueryWrapper<>(new Video()).eq(Video::getShortVideo, false));
        if (count > 100) {
            videoList = baseMapper.recommendLists();
        } else {
            videoList = baseMapper.recommendList();
        }
        for (Video v : videoList) {
            // 获取收藏数量
            Favorites favorites = new Favorites();
            favorites.setVideoId(v.getId());
            long favoritesCount = favoritesService.count(new QueryWrapper<>(favorites));
            v.setFavoritesCount(favoritesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(favoritesCount) : StrUtil.toString(favoritesCount));
            // 获取点赞数量
            Likes likes = new Likes();
            likes.setVideoId(v.getId());
            long likesCount = likesService.count(new QueryWrapper<>(likes));
            v.setLikesCount(likesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(likesCount) : StrUtil.toString(likesCount));
        }
        return videoList;
    }
}
